[0x02] NASM汇编 [输出hello world!]

您所在的位置:网站首页 汇编语言hallow world [0x02] NASM汇编 [输出hello world!]

[0x02] NASM汇编 [输出hello world!]

2023-10-17 14:52| 来源: 网络整理| 查看: 265

nasm官方文档:https://www.nasm.us/xdoc/2.14.03rc2/nasmdoc.pdf

当遇到问题时,可以在文档中查询,文档是英文的,需要一定的英语阅读能力。

下面是一个输出的例子。

; hello.asm section .data msg db 'hello, world!',0xa len equ $-msg section .text global _start _start: mov rax, 4 mov rbx, 1 mov rcx, msg mov rdx, len int 0x80 mov rax, 1 int 0x80

在ubuntu 64位的机器上编译运行:

nasm -f elf64 -o hello.o hello.asm ld -o hello hello.o ./hello

这个时候会在控制台中看到输出结果hello, world!

程序分析:

section是程序段的意思,首先定义了.data数据段,在data数据段中,定义了2个变量msg和len。

.text段中,_start作为程序的入口点,当然可以换成其他的名字。

之后,使用了mov指令,对寄存器rax,rbx,rcx,rdx等赋值,最后执行int 0x80,进行系统调用。

我们可以使用系统调用,就是系统函数。rax保存系统调用号,4是System_write的系统调用号,可以在文件/usr/include/x86_64-linux-gnu/asm/unistd_32.h查看系统调用号。不同的系统位置可能不同。

使用man 2 write查看write的用法,找到write函数的原型:

ssize_t write(int fd, const void *buf, size_t count);

fd是文件描述符,buf是指向要输出内容的指针,而count是输出的数量,按字节计数。

mov rbx, 1 mov rcx, msg mov rdx, len

rbx,rcx,rdx保存系统调用的参数,即fd=1,buf=msg,count=len

当参数更多时,使用下面的寄存器保存系统调用的参数:rbx,rcx,rdx,rsi,rdi,rbp

int 0x80指令进行系统调用。

 

不过,现在可以使用syscall指令来替换int 0x80,这时候,规则有了变化,rax依然保存系统调用号,而系统调用的参数使用下面的寄存器,用户模式的系统调用依次传递的寄存器为:rdi,rsi,rdx,rcx,r8和r9;而内核接口的系统调用依次传递的寄存器为:rdi,rsi,rdx,r10,r8和r9。这里只有第4个参数不同。我们使用的是用户模式的系统调用,因此,上面的hello.asm代码可以修改为下面这样:

; hello2.asm seciont .data msg db 'hello, world',0xa len equ $-msg section .text global _start _start: mov rax, 1 mov rdi, 1 mov rsi, msg mov rdx, len syscall mov rax, 60 syscall

这里发生了一些变化,当使用syscall进行系统调用时,需要使用64位的系统调用号,在文件/usr/include/x86_64-linux-gnu/asm/unistd_64.h查看64位的系统调用号。

write的系统调用号是1,而exit的系统调用号是60.



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3